﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.Utilities;
#if !DOT_NET
using Windows.Foundation;
using Windows.Storage;

#endif

namespace StyleMVVM.Configuration
{
	public sealed class DefaultConfigurationStorageProvider : IConfigurationStorageProvider
	{
		private Dictionary<string, object> values = new Dictionary<string, object>();

		public static void RegisterExport(IDependencyInjectionContainer container)
		{
			container.Register(typeof(DefaultConfigurationStorageProvider)).
			          As(typeof(IConfigurationStorageProvider)).
			          ActivationMethod("Activate");
		}

		public async void Activate()
		{
			try
			{
				bool openConfig = true;

#if DOT_NET
				openConfig = File.Exists("Configuration.xml");
#endif

				if (openConfig)
				{
					values =
						await ObjectSerializationHelper.DeserializeFromFile("Configuration.xml",
						                                                    typeof(Dictionary<string, object>),
						                                                    ReflectionService.KnownTypes) as Dictionary<string, object>;
				}
			}
			catch (Exception)
			{
			}

			if (values == null)
			{
				values = new Dictionary<string, object>();
			}
		}

		public bool CanSet
		{
			get { return true; }
		}

#if NETFX_CORE
		public IAsyncOperation<ConfigValuePair> GetValue(string valueName, Type valueType)
		{
			return InternalGetValue(valueName).AsAsyncOperation();
		}
		
		public IAsyncOperation<bool> SetValue(string valueName, object newValue)
		{
			return InternalSetValue(valueName, newValue).AsAsyncOperation();
		}
		
		public IAsyncOperation<ConfigValuePair> GetUserValue(string username, string valueName, Type valueType)
		{
			throw new NotImplementedException();
		}

		public IAsyncOperation<bool> SetUserValue(string username, string valueName, object newValue)
		{
			throw new NotImplementedException();
		}
#else
		public Task<ConfigValuePair> GetValue(string valueName, Type valueType)
		{
			return InternalGetValue(valueName);
		}

		public Task<bool> SetValue(string valueName, object newValue)
		{
			return InternalSetValue(valueName, newValue);
		}

		public Task<ConfigValuePair> GetUserValue(string username, string valueName, Type valueType)
		{
			throw new NotImplementedException();
		}

		public Task<bool> SetUserValue(string username, string valueName, object newValue)
		{
			throw new NotImplementedException();
		}
#endif

		internal Task<ConfigValuePair> InternalGetValue(string valueName)
		{
			object returnValue;

			bool foundValue = values.TryGetValue(valueName, out returnValue);

			if (foundValue)
			{
				return InternalTaskHelper.ReturnTask(new ConfigValuePair { ConfigValue = returnValue, ReturnValue = true });
			}

			return InternalTaskHelper.ReturnTask(new ConfigValuePair { ConfigValue = null, ReturnValue = false });
		}

		internal async Task<bool> InternalSetValue(string valueName, object newValue)
		{
			Dictionary<string, object> newValues = new Dictionary<string, object>(values);

			newValues[valueName] = newValue;

			await ObjectSerializationHelper.SerializeToFile("Configuration.xml",
			                                                newValues,
			                                                CreationCollisionOption.ReplaceExisting,
			                                                ReflectionService.KnownTypes);

			values = newValues;

			return true;
		}
	}
}